import type { ReactNode } from 'react';
import * as React from 'react';
// @ts-ignore
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';

interface QuestionListInterface<T> {
  value: T[];
  grid?: number;
  orderKey?: string;
  onChange?: (newValue: T[], dragEndResult: Record<string, any>) => void;
  children: (item: T, index: number, provided: any) => React.ReactNode;
  dataId?: string; // 唯一id
  unDragItemRender?: (record: any) => ReactNode;
  // 是否自定义设置拖拽块
  autoHandleDrag?: boolean;
  isDropDisabled?: boolean;
}
function DroppableList<T extends Record<string, any>>(props: QuestionListInterface<T>) {
  const {
    value,
    grid = 8,
    onChange,
    children,
    dataId = 'id',
    orderKey = 'questionOrder',
    unDragItemRender,
    autoHandleDrag,
    isDropDisabled
  } = props;

  const reorder = (list: any[], startIndex: number, endIndex: number): any[] => {
    const result = Array.from(list);
    const startOrder = result[startIndex]?.[orderKey];
    const endOrder = result[endIndex]?.[orderKey];
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    result[startIndex][orderKey] = startOrder;
    result[endIndex][orderKey] = endOrder;
    return result.map((item, idx: number) => ({ ...item, [orderKey]: idx + 1 }));
  };

  const getItemStyle = (isDragging: boolean, draggableStyle: Record<string, any>) => ({
    userSelect: 'none',
    padding: grid * 2,
    margin: `0 0 ${grid}px 0`,
    // border: isDragging ? '1px solid #ccc' : 'unset',
    background: isDragging ? '#fafafa' : 'unset',
    ...draggableStyle
  });

  const getListStyle = (isDraggingOver: boolean) => ({
    padding: grid,
    border: isDraggingOver ? '1px solid #ccc' : 'unset',
    borderRadius: 6
  });

  const onDragEnd = (result: Record<string, any>) => {
    onChange?.(reorder(value, result.source?.index, result.destination?.index), result);
  };

  const renderChild = (item: T, index: number, provided: any) => {
    if (typeof children === 'function') {
      return children(item, index, provided);
    }
    return children;
  };

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId='droppable' isDropDisabled={isDropDisabled}>
        {(provided: any, snapshot: any) => (
          <div
            {...provided.droppableProps}
            ref={provided.innerRef}
            style={getListStyle(snapshot.isDraggingOver)}>
            {value &&
              value.map((item, index) => (
                <div key={item[dataId].toString()}>
                  <Draggable
                    key={item[dataId].toString()}
                    draggableId={item[dataId].toString()}
                    index={index}
                    isDragDisabled={!!item.isDragDisabled}>
                    {(provided1: any, snapshot1: any) => (
                      <div
                        ref={provided1.innerRef}
                        {...provided1.draggableProps}
                        {...(autoHandleDrag ? {} : provided1.dragHandleProps)}
                        style={getItemStyle(snapshot1.isDragging, provided1.draggableProps.style)}>
                        {renderChild(item, index, provided1)}
                      </div>
                    )}
                  </Draggable>
                  {unDragItemRender && unDragItemRender?.(item)}
                </div>
              ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}

export default DroppableList;
